package org.beasy.controls.treeClasses
{
	import flash.events.Event;
	
	import mx.binding.utils.BindingUtils;
	import mx.collections.ArrayCollection;
	import mx.controls.CheckBox;
	import mx.controls.treeClasses.TreeItemRenderer;
	import mx.controls.treeClasses.TreeListData;
	
	import org.beasy.controls.listClasses.IListItemData;
	import org.beasy.events.ItemRendererEvent;
	
	/**
	 * 增强的在Tree组件上使用的ItemRenderer
	 * 支持级联选中，反选，数据源同步.
	 * 
	 * @author Marco
	 */	
	public class CheckBoxTreeRendererPlus extends TreeItemRenderer
	{
		public function CheckBoxTreeRendererPlus()
		{
			super();
		}
		
		//--------------------------------------------------------------------------
		//
		//  Variables
		//
		//--------------------------------------------------------------------------

		/**
		 * @private
		 */		
		protected var checkBox:CheckBox = null;
		
		/**
		 * @private
		 */		
		private var _dataDirty:Boolean;
		
		
		//--------------------------------------------------------------------------
		//
		//  Overridens
		//
		//--------------------------------------------------------------------------
		
		/**
		 * @protected
		 * 
		 * 重写父类setter data方法
		 */		
		override public function set data(value:Object) : void
		{
			_dataDirty = true;
			invalidateProperties();
			super.data = value;
		}
		
		/**
		 * @protected
		 * 
		 * 重写父类的<code>createChildren()</code>方法
		 * 在此方法内创建checkBox实例.
		 */		
		override protected function createChildren() : void
		{
			super.createChildren();
			
			checkBox = new CheckBox();
			checkBox.addEventListener(Event.CHANGE, changeHandler);
			addChild( checkBox );
		}
		
		/**
		 * @protected
		 * 
		 * 重写父类的<code>commitProperties()</code>方法
		 * 在此方法内进行发生绑定.
		 */		
		override protected function commitProperties() : void
		{
			super.commitProperties();
			if( _dataDirty )
			{
				_dataDirty = false;
				
				var item:IListItemData = IListItemData( data );
				BindingUtils.bindProperty(checkBox, "selected", item, "selected");
				BindingUtils.bindProperty(checkBox, "enabled", item, "selectable");
			}
		}
		
		/**
		 * @protected
		 * 
		 * 重写父类的<code>updateDisplayList()</code>方法
		 * 重新排列位置, 将label后移
		 */		
		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
		{
			super.updateDisplayList(unscaledWidth, unscaledHeight);
			var startx:Number = data ? TreeListData( listData ).indent : 0;
			
			if (disclosureIcon)
			{
				disclosureIcon.x = startx;
				
				startx = disclosureIcon.x + disclosureIcon.width;
				
				disclosureIcon.setActualSize(disclosureIcon.width,
					disclosureIcon.height);
				
				disclosureIcon.visible = data ?
					TreeListData( listData ).hasChildren :
					false;
			}
			
			if (icon)
			{
				icon.x = startx;
				startx = icon.x + icon.measuredWidth;
				icon.setActualSize(icon.measuredWidth, icon.measuredHeight);
			}
			
			if ( checkBox )
			{
				checkBox.move(startx, ( unscaledHeight - checkBox.height ) / 2 );
				label.x = startx + checkBox.getExplicitOrMeasuredWidth();
			}
		}
		
		//--------------------------------------------------------------------------
		//
		//  Methodes
		//
		//--------------------------------------------------------------------------
		
		/**
		 * @private
		 */		
		private function changeHandler( event:Event ):void
		{
			IListItemData(data).selected = checkBox.selected;
			var item:IListItemData = IListItemData( data );
			checkChildren(item);
			checkPreLevel(item);
			
			var evt:ItemRendererEvent;
			if( !item.children && item.id != null )
			{
				evt = new ItemRendererEvent( ItemRendererEvent.TREE_ITEM_CLICK, true);
				evt.item = item;
				evt.itemRenderer = this;
				dispatchEvent( evt );
			}
			else if( item.children )
			{
				var collection:ArrayCollection = new ArrayCollection();
				getDescendant(item, collection);
				evt = new ItemRendererEvent( ItemRendererEvent.TREE_FOLDER_CLICK, true );
				evt.children = collection;
				evt.itemRenderer = this;
				dispatchEvent( evt );
			}
		}
		
		private function getDescendant( item:IListItemData, collection:ArrayCollection ):void
		{
			for each( var node:IListItemData in item.children )
			{
				if( node.children )
				{
					getDescendant(node, collection);
				}
				else
				{
					collection.addItem( node );
				}
			}
		}
		
		/**
		 * 递归算法，循环遍历所有子集
		 */		
		private function checkChildren(item:IListItemData):void
		{
			for each( var node:IListItemData in item.children )
			{
				if (node.selected != item.selected)
					node.selected = item.selected;
				if( node.children )
					checkChildren( node );
			}
		}
		
		/**
		 * 递归当前项父级
		 */		
		private function checkPreLevel(item:IListItemData):void
		{
			if( !item.parent )
				return;
			
			var flag:Boolean = true;
			for each( var node:IListItemData in item.parent.children )
			{
				if( !node.selected )
				{
					flag = false;
					break;
				}
			}
			
			if( item.parent && flag != item.parent.selected )
			{
				item.parent.selected = flag;
				checkPreLevel( item.parent );
			}
		}
		
	}
}